// 文件: cObject.ts

import { CCInteger, Color, Component, Node, PhysicsGroup, Quat, UITransform, Vec2, Vec3, _decorator, ccenum } from 'cc';
import { cBody } from './Body';
import { cCollider } from './Collider';
import { ShapeType, cBox, cPolygon, cShape, cSphere } from './Shape';

const { ccclass, property } = _decorator;

export enum Trigger {
    default = 0,
    enter = 1,
    stay = 2,
    exit = 3,
};

export enum Dirty {
    R = 1,
    T = 2,
    S = 4,
    RTS = 7,
    RS = R | S,
    NON = 0,
};

ccenum(ShapeType);
@ccclass('cObject')
export class cObject extends Component {
    @property({ group: "Body" })
    trigger: boolean = false;

    @property({ 
        type: PhysicsGroup, 
        group: "Body",
        tooltip: "设置该物体所属的组。"
    })
    group = PhysicsGroup.DEFAULT;

    // 【【【重要修改：新增 Mask 属性】】】
    @property({
        type: PhysicsGroup,
        group: "Body",
        tooltip: "设置该物体可以与哪些组发生碰撞。按住 Ctrl 或 Command 可多选。"
    })
    mask: number = 0; // mask 的初始值设为 0，表示默认不与任何组碰撞

    @property({ type: ShapeType, group: "Shape" })
    type: ShapeType = ShapeType.Box;

    @property({ group: "Shape" })
    center: Vec3 = new Vec3();

    @property({ group: "Shape", visible() { return this.type == ShapeType.Box; } })
    size: Vec3 = new Vec3();

    @property({ group: "Shape", visible() { return this.type == ShapeType.Sphere; } })
    radius: number = 0;

    @property({ type: [Vec2], group: "Shape", visible() { return this.type == ShapeType.Polygon; } })
    points: Array<Vec2> = [];


    @property({ group: "Agent" })
    agent: boolean = false;


    @property({ min: 0.01, max: 1.0, step: 0.01, group: "Agent", visible() { return this.agent; } })
    weight: number = 0.5;

    @property({ group: "Agent", visible() { return this.agent; } })
    maxRadius: number = 0;

    @property({ group: "Agent", visible() { return this.agent; } })
    maxVelocity: number = 0;

    tryVelocity: Vec3 = new Vec3();
    velocity: Vec3 = new Vec3();
    isDirty: Dirty = Dirty.RTS;
    shape: cShape = null;
    body: cBody = null;


    protected onLoad() {
        // 在 onLoad 中只做不依赖其他模块的事情
        switch (this.type) {
            case ShapeType.Box:
                this.shape = new cBox(this.center, this.size);
                break;
            case ShapeType.Sphere:
                this.shape = new cSphere(this.center, this.radius);
                break;
            case ShapeType.Polygon:
                this.shape = new cPolygon(this.center, this.points);
                break;
        }
    }

    protected start() {
        // 在 start 中执行依赖性强的初始化
        this.body = cCollider.inst.create(this);
        this.body.shape = this.shape;
        this.body.group = this.group;
        
        // 【【【重要修改：直接使用编辑器设置的 mask】】】
        // 不再从 PhysicsSystem 读取 mask，而是直接使用我们在属性检查器中设置的 mask
        this.body.mask = this.mask; 
        
        this.body.isAgent = this.agent;
        this.body.weight = this.weight;
        this.body.neighborDist = this.maxRadius;
        this.body.maxVelocity = this.maxVelocity;
        
        cCollider.inst.insert(this.body);
        this.isDirty = Dirty.RTS;
    }

    // --- 其他函数保持不变 ---

    setPosition(position: Vec3) {
        this.node.position = position;
        this.isDirty |= Dirty.T;
    }
    setRotation(rotation: Quat) {
        this.node.rotation = rotation;
        this.isDirty |= Dirty.R;
    }
    setScale(scale: Vec3) {
        this.node.scale = scale;
        this.isDirty |= Dirty.S;
    }
    setAnchor(anchor: Vec2) {
        let c0 = this.center;
        let c1 = this.shape.center;
        let uts = this.node.getComponent(UITransform);
        if (uts) {
            uts.anchorPoint = anchor;
            let s = uts.contentSize;
            c1.x = (0.5 - anchor.x) * s.width + c0.x;
            c1.y = (0.5 - anchor.y) * s.height + c0.y;
            this.isDirty |= Dirty.T;
        }
    }

    getRotation() { return this.node.rotation; }
    getPosition() { return this.node.position; }
    getScale() { return this.node.scale; }

    remove(retrieve: boolean = true) {
        cCollider.inst.remove(this.body, retrieve);
        this.node.removeFromParent();
        return this.node;
    }

    insert(parent: Node) {
        cCollider.inst.insert(this.body, true);
        if (this.node.parent != parent)
            parent.addChild(this.node);
    }


    setAnimation(name: string) { }
    setColor(color: Color) { }
    init() { }

    onTrigger(b: cBody, trigger: Trigger) {
        switch (trigger) {
            case Trigger.enter:
                this.onTriggerEnter(b, trigger);
                break;
            case Trigger.stay:
                this.onTriggerStay(b, trigger);
                break;
            case Trigger.exit:
                this.onTriggerExit(b, trigger);
                break;
        }
    }

    protected onTriggerEnter(b: cBody, trigger: Trigger) { }
    protected onTriggerStay(b: cBody, trigger: Trigger) { }
    protected onTriggerExit(b: cBody, trigger: Trigger) { }

    hasChangeDirty() {
        let isDirty = this.isDirty;
        let flag = this.node.hasChangedFlags;
        if (flag) {
            if (flag & Node.TransformBit.POSITION) isDirty |= Dirty.T;
            if (flag & Node.TransformBit.ROTATION) isDirty |= Dirty.R;
            if (flag & Node.TransformBit.SCALE) isDirty |= Dirty.S;
        }
        this.isDirty = Dirty.NON;
        return isDirty;
    }

    onDestroy() {
        if (this.body) {
            cCollider.inst.remove(this.body, true);
        }
        this.unscheduleAllCallbacks();
        this.shape = null;
        this.body = null;
    }
}
